using System.Collections;
using System.Collections.Generic;
using System.Threading;

namespace Framework.Core.Collections
{
    internal class ConcurrentHashset<T> : ICollection<T>
    {
        private readonly ICollection<T> internalHashset;
        private readonly ReaderWriterLockSlim syncRoot = new ReaderWriterLockSlim();

        public ConcurrentHashset()
        {
            internalHashset = new HashSet<T>();
        }

        public ConcurrentHashset(IEnumerable<T> enumerable)
        {
            internalHashset = new HashSet<T>(enumerable);
        }

        public IEnumerator<T> GetEnumerator()
        {
            syncRoot.EnterReadLock();
            try
            {
                return internalHashset.GetEnumerator();
            }
            finally
            {
                syncRoot.ExitReadLock();
            }
        }

        public void Add(T item)
        {
            syncRoot.EnterWriteLock();

            try
            {
                internalHashset.Add(item);
            }
            finally
            {
                syncRoot.ExitWriteLock();
            }
        }

        public void Clear()
        {
            syncRoot.EnterWriteLock();

            try
            {
                internalHashset.Clear();
            }
            finally
            {
                syncRoot.ExitWriteLock();
            }
        }

        public bool Contains(T item)
        {
            syncRoot.EnterReadLock();
            try
            {
                return internalHashset.Contains(item);
            }
            finally
            {
                syncRoot.ExitReadLock();
            }
        }

        public void CopyTo(T[] array, int arrayIndex)
        {
            syncRoot.EnterWriteLock();

            try
            {
                internalHashset.CopyTo(array, arrayIndex);
            }
            finally
            {
                syncRoot.ExitWriteLock();
            }
        }

        public bool Remove(T item)
        {
            syncRoot.EnterWriteLock();

            try
            {
                return internalHashset.Remove(item);
            }
            finally
            {
                syncRoot.ExitWriteLock();
            }
        }

        public int Count
        {
            get
            {
                syncRoot.EnterReadLock();
                try
                {
                    return internalHashset.Count;
                }
                finally
                {
                    syncRoot.ExitReadLock();
                }
            }
        }

        public bool IsReadOnly
        {
            get
            {
                syncRoot.EnterReadLock();
                try
                {
                    return internalHashset.IsReadOnly;
                }
                finally
                {
                    syncRoot.ExitReadLock();
                }
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
}